﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<title>Entity Framework Core</title>
<link type="text/css" rel="stylesheet" href="bootstrap.min.css" />
</head>

<body>

<div class="document-contents">

<h3>Introduction</h3>
<p>
<a href="https://www.nuget.org/packages/Abp.EntityFrameworkCore" target="_blank">
Abp.EntityFrameworkCore</a> nuget package is used to integrate to Entity 
Framework (EF) Core ORM framework. After installing this package, we should also add 
a <a href="Module-System.html">DependsOn</a> attribute for <strong>
AbpEntityFrameworkCoreModule</strong>.</p>
	<h3>DbContext</h3>
	<p>EF Core requires to define a class derived from DbContext. In ABP, we 
	should derive from <strong>AbpDbContext</strong> as shown below:</p>
	<pre lang="cs">public class MyDbContext : <strong>AbpDbContext</strong>
{
    public DbSet&lt;Product&gt; Products { get; set; }

    public MyDbContext(<strong>DbContextOptions&lt;MyDbContext&gt; options</strong>)
        : base(options)
    {
    }
}</pre>
	<p>Constructor should get a <strong>DbContextOptions&lt;T&gt;</strong> as shown 
	above.</p>
	<h3>Configuration</h3>
	<h4>In Startup Class</h4>
	<p>For an ASP.NET Core project, you will have a <strong>Startup</strong> 
	file and you can use <strong>AddDbContext</strong> extension method of EF 
	Core as you always do:</p>
	<pre lang="cs">public IServiceProvider ConfigureServices(IServiceCollection services)
{
    ...
    
<strong>    services.AddDbContext&lt;MyDbContext&gt;(options =&gt;
    {
        options.UseSqlServer(Configuration.GetConnectionString(&quot;Default&quot;));
    });</strong>

    ...
}</pre>
	<p>This approach is standard, simple and enough for ABP. In this approach, 
	connection string is static (because we are always using the "Default" 
	connection string). If you have single database for a dbcontext, that's fine. But 
	if you want to dynamically determine connection string and better integrate 
	to ABP's connection string system, use <strong>AddAbpDbContext</strong> method:</p>
	<pre lang="cs">services.<strong>AddAbpDbContext</strong>&lt;MyDbContext&gt;(options =&gt;
{
    options.DbContextOptions.UseSqlServer(options.ConnectionString);
});</pre>
	<p>We used given connection string and used Sql Server as database provider. <strong>options.ConnectionString</strong> 
	is the <strong>default connection string</strong> (see next section) 
	normally. But ABP uses IConnectionStringResolver to determine it. So, 
	this behaviour can be changed and connection string can be determined 
	dynamically. The action passed to AddDbContext is called whenever a DbContext instance 
	will be created. So, you also have a chance to return different connection 
	string conditionally.</p>
	<p>So, where to set default connection string?</p>
	<h4>In Module PreInitialize</h4>
	<p>You can do it in PreInitialize of your module as shown below:</p>
	<pre lang="cs">public class MyEfCoreAppModule : AbpModule
{
    public override void PreInitialize()
    {
<strong>        Configuration.DefaultNameOrConnectionString = GetConnectionString(&quot;Default&quot;);</strong>
        ...
    }
}</pre>
	<p>For non web projects, we will not have a Startup class. In that case, we 
	can use
<strong>        Configuration.Modules.AbpEfCore().AddDbContext</strong> method 
	here to configure DbContext, as shown below:</p>
	<pre lang="cs">Configuration.Modules.AbpEfCore().AddDbContext&lt;MyDbContext&gt;(options =&gt;
{
    options.DbContextOptions.UseSqlServer(options.ConnectionString);
});</pre>

			<h3 id="DocRepositories">Repositories</h3>
			<p>Repositories are used to abstract data access from higher layers. 
			See <a href="Repositories.html">repository documentation</a> for 
			more.&nbsp;</p>
			<h4 id="DocImplRepositories">Default Repositories</h4>
			<p>
				<a href="http://www.nuget.org/packages/Abp.EntityFrameworkCore" target="_blank">Abp.EntityFrameworkCore</a> 
			implements default repositories for all entities defined in your 
			DbContext. You don't have to create repository classes to use 
predefined repository methods. Example:</p>
			<pre lang="cs">public class PersonAppService : IPersonAppService
{
    private readonly <strong>IRepository&lt;Person&gt; _personRepository</strong>;

    public PersonAppService(<strong>IRepository&lt;Person&gt; personRepository</strong>)
    {
        _personRepository = personRepository;
    }

    public void CreatePerson(CreatePersonInput input)
    {        
        person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };

        <strong>_personRepository.Insert(person);
</strong>    }
}</pre>

			<p>PersonAppService contructor-injects <strong>IRepository&lt;Person&gt;</strong> and 
uses the <strong>Insert</strong> method. In this way, you can easily inject
				<strong>IRepository&lt;TEntity&gt;</strong> (or IRepository&lt;TEntity, TPrimaryKey&gt;) and 
use predefined methods. See <a href="/Pages/Documents/Repositories">repository 
documentation</a> for all predefined methods.</p>

			<h4 id="DocCustomRepositoryMethods">Custom Repositories</h4>
			<p>If standard repository methods are not sufficient, you can create 
			custom repository classes for your entities.</p>
			<h5 id="DocAppBaseRepo">Application Specific Base Repository Class</h5>

			<p>ASP.NET Boilerplate provides a base class <strong>EfCoreRepositoryBase</strong> 
to implement repositories easily. To implement <strong>IRepository</strong> interface, you can 
just derive your repository from this class. But it's better to create your own 
base class that extens EfRepositoryBase. Thus, you can add shared/common methods 
to your repositories easily. An example base class all for repositories of a <em>SimpleTaskSystem</em> application:</p>
			<pre lang="cs">//Base class for all repositories in my application
public class SimpleTaskSystemRepositoryBase&lt;TEntity, TPrimaryKey&gt; : <strong>EfCoreRepositoryBase&lt;SimpleTaskSystemDbContext, TEntity, TPrimaryKey&gt;</strong>
    where TEntity : class, IEntity&lt;TPrimaryKey&gt;
{
    public SimpleTaskSystemRepositoryBase(<strong>IDbContextProvider&lt;SimpleTaskSystemDbContext&gt; dbContextProvider</strong>)
        : base(dbContextProvider)
    {
    }

    //add common methods for all repositories
}

//A shortcut for entities those have integer Id
public class SimpleTaskSystemRepositoryBase&lt;TEntity&gt; : <strong>SimpleTaskSystemRepositoryBase&lt;TEntity, int&gt;</strong>
    where TEntity : class, IEntity&lt;int&gt;
{
    public SimpleTaskSystemRepositoryBase(<strong>IDbContextProvider&lt;SimpleTaskSystemDbContext&gt; dbContextProvider</strong>)
        : base(dbContextProvider)
    {
    }

    //do not add any method here, add to the class above (because this class inherits it)
}</pre>
			<p>Notice that we're inheriting from EfCoreRepositoryBase&lt;<strong>SimpleTaskSystemDbContext</strong>, TEntity, TPrimaryKey&gt;. 
This declares to ASP.NET Boilerplate to use SimpleTaskSystemDbContext in our 
repositories.</p>
			<h5>Custom Repository Example</h5>

			<p>To implement a custom repository, just derive from your application specific 
base repository class we created above.</p>
			<p>Assume that we have a Task entity that can be assigned to a Person (entity) 
and a Task has a State (new, assigned, completed... and so on). We may need to 
write a custom method to get list of Tasks with some conditions and with 
AssisgnedPerson property pre-fetched (included) in a single database query. See the example 
code:</p>
			<pre>public interface ITaskRepository : <strong>IRepository&lt;Task, long&gt;
</strong>{
    List&lt;Task&gt; GetAllWithPeople(int? assignedPersonId, TaskState? state);
}

public class TaskRepository : <strong>SimpleTaskSystemRepositoryBase&lt;Task, long&gt;, ITaskRepository
</strong>{
    public TaskRepository(IDbContextProvider&lt;SimpleTaskSystemDbContext&gt; dbContextProvider)
        : base(dbContextProvider)
    {
    }

    public List&lt;Task&gt; GetAllWithPeople(int? assignedPersonId, TaskState? state)
    {
        var query = GetAll();

        if (assignedPersonId.HasValue)
        {
            query = query.Where(task =&gt; task.AssignedPerson.Id == assignedPersonId.Value);
        }

        if (state.HasValue)
        {
            query = query.Where(task =&gt; task.State == state);
        }

        return query
            .OrderByDescending(task =&gt; task.CreationTime)
            .Include(task =&gt; task.AssignedPerson)
            .ToList();
    }
}</pre>
			<p>
				<strong class="auto-style2">We first defined </strong>ITaskRepository and 
then implemented it.<strong> GetAll()</strong> returns <strong>IQueryable&lt;Task&gt;</strong>, then we can add some
				<strong>Where</strong> filters using given parameters. Finally we can call
				<strong>ToList()</strong> to get list of 
Tasks.</p>
			<p>You can also use <strong>Context </strong>object in repository methods to 
reach to your DbContext and directly use Entity Framework APIs.&nbsp;</p>
	<p><strong>Note</strong>: Define the custom repository <strong>interface
	</strong>in the <strong>domain/core</strong> layer, <strong>implement
	</strong>it in the <strong>EntityFrameworkCore </strong>project for layered 
	applications. Thus, you can inject the interface from any project without 
	referencing to EF Core.</p>
	<h5>Replacing Default Repositories</h5>
	<p>Even you have created a TaskRepository as shown above, any class can 
	still <a href="Dependency-Injection.html">inject</a> IRepository&lt;Task, long&gt; 
	and use it. That's not a problem in most cases. But, what if you <strong>
	overrided</strong> a base method in your custom repository? Say that you 
	have overrided Delete method in your custom repository to add a custom 
	behaviour on delete. If a class injects IRepository&lt;Task, long&gt; and use the 
	default repository to Delete a task, your custom behaviour will not work. To 
	overcome this issue, you can replace your custom repository implementation 
	with the default one like shown below:</p>
	<pre lang="cs">Configuration.ReplaceService&lt;<strong>IRepository&lt;Task, Guid&gt;</strong>&gt;(() =&gt;
{
    IocManager.IocContainer.Register(
        Component.For&lt;<strong>IRepository&lt;Task, Guid&gt;, ITaskRepository, TaskRepository</strong>&gt;()
            .ImplementedBy&lt;<strong>TaskRepository</strong>&gt;()
            .<strong>LifestyleTransient</strong>()
    );
});</pre>
	<p>We registered TaskRepository for IRepository&lt;Task, Guid&gt;, 
	ITaskRepository and TaskRepository. So, any one of these can be injected to 
	use the TaskRepository.</p>
			<h4>Repository Best Practices</h4>
			<ul>
				<li><strong>Use default repositories</strong> wherever it's 
				possible. You can use default repository even you have a custom 
				repository for an entity (if you will use standard repository 
				methods).</li>
				<li>Always create <strong>repository base class</strong> for 
				your application for custom repositories, as defined above.</li>
				<li>Define <strong>interfaces </strong>for your custom 
				repositories in <strong>domain layer</strong> (.Core project in 
				startup template), custom repository <strong>classes </strong>in
				<strong>.EntityFrameworkCore</strong> project if you want to 
				abstract EF Core from your domain/application.</li>
			</ul>

	<h3>Missing Points</h3>
	<p>Abp.EntityFrameworkCore module currently does not support following ABP 
	features:</p>
	<ul>
		<li><strong>Data Filters</strong>: Abp.EntityFramework module uses 
		EntityFramework.DynamicFilters to accomplish automatic
		<a href="Data-Filters.html">data filtering</a>. Currently, it
		<a href="https://github.com/jcachat/EntityFramework.DynamicFilters/issues/48" target="_blank">
		does not support</a> EF Core. While some other libraries (like EF Plus) 
		do it, as our investigation it's implemented in a limited way (for 
		example, EF+ does not support filtering of navigation properties).</li>
		<li><strong>DateTime normalization</strong>: Abp.EntityFramework module 
		normalizes DateTime properties of entities while getting them from 
		database. This is not possible for Abp.EntityFrameworkCore yet.</li>
	</ul>

</div>

</body>

</html>
